using System;
using System.Collections.Generic;
using Microsoft.Modeling.StoryboardDesigner;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

namespace Microsoft.Modeling.StoryboardDesigner
{
    public partial class StoryboardDesignerDomainModel
    {
        private void AddResizeMultiLinesRules(List<Type> types)
        {
            types.Add(typeof(ResizeMultiLineDecoratorChangeRule));
            types.Add(typeof(ResizeStoryboardPelChangeRule));
        }
    }

    /// <summary>
    /// Rule to handle multi-line properties being edited - notify the
    /// Pels to resize themselves.
    /// </summary>
    [RuleOn(typeof(Scenario), FireTime = TimeToFire.TopLevelCommit)]
    [RuleOn(typeof(StoryboardElement), FireTime = TimeToFire.TopLevelCommit)]
    internal class ResizeMultiLineDecoratorChangeRule : ChangeRule
    {
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            if(e == null || e.ModelElement == null)
            {
                return;
            }

            // Assume that the multi-line property is always called Title
            if(e.DomainProperty.Name != "Title")
            {
                return;
            }

            // We are only interested in StoryboardElements that
            // are mapped to StoryboardShape shapes, or ScenarioShapes.
            foreach(PresentationElement pel in PresentationViewsSubject.GetPresentation(e.ModelElement))
            {
                IStoryboardPel stbPel = pel as IStoryboardPel;

                if(stbPel != null)
                {
                    // Tell the shape to that the multi-line decorator
                    // property value has changed.
                    stbPel.UpdateMultiLineDecoratorSize();
                }
            }
        }
    }

    /// <summary>
    /// Handle shapes with multi-line decorators being resized.
    /// </summary>
    [RuleOn(typeof(NodeShape), FireTime = TimeToFire.TopLevelCommit, Priority = DiagramFixupConstants.ShapeAnchoringRulePriority)]
    internal class ResizeStoryboardPelChangeRule : ChangeRule
    {
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            if(e == null || e.ModelElement == null)
            {
                return;
            }

            // Only interested in changes to absolute bounds
            if(e.DomainProperty.Id != NodeShape.AbsoluteBoundsDomainPropertyId)
            {
                return;
            }

            // We are only interested in shapes that implement the IStoryboardPel 
            // interface.
            IStoryboardPel shape = e.ModelElement as IStoryboardPel;

            if(shape != null)
            {
                shape.UpdateMultiLineDecoratorSize();
            }
        }
    }
}